package com.qf.rpc.server;

import com.qf.rpc.SerializeUtil;
import com.qf.rpc.ZkUtil;
import com.qf.rpc.protocol.Request;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class RpcServer {
    //private static Map<String, Object> spring = new HashMap<>();

    public static void main(String[] args) {
//        UserServiceImpl service = new UserServiceImpl();
//        RpcService anno = service.getClass().getAnnotation(RpcService.class);
//        System.out.println(anno.value());
//        System.out.println(anno.version());

        ApplicationContext spring = new ClassPathXmlApplicationContext("spring.xml");
        ZkUtil util = new ZkUtil();
        util.createConnection();
        Map<String, Object> serviceBeanMap = spring.getBeansWithAnnotation(RpcService.class);//可以拿到有指定注解的bean
        for (Object o : serviceBeanMap.values()) {
            RpcService anno = o.getClass().getAnnotation(RpcService.class);
            String name = "/"+anno.value().getName();
            if (util.exist(name, false) != null) {
                util.deleteNode(name);//如果不删掉，不能再创建节点
            }
            util.createNode(name, "127.0.0.1:8888");
        }
        //模拟spring容器中的bean
        // spring.put("com.qf.rpc.TestService", new TestServiceImpl());
        // spring.put("com.qf.rpc.UserService", new UserServiceImpl());
        //如果使用注册中心，在服务端启动的时候，应该把服务端所有的服务，ip和端口号写到zookeeper中
        // 1.实例化一个ServerSocket的对象
        ServerSocket serverSocket = null;
        OutputStream output = null;// 用于向别人发消息
        InputStream input = null;// 用于读取别人发过来的消息
        try {
            serverSocket = new ServerSocket(8888);
            System.out.println("等待服务端的连接...");
            // 2.监听，获取连接到的客户端 注意：在未连接成功之前，将一直处于阻塞状态
            Socket socket = serverSocket.accept();
            System.out.println("连接成功");
            // 3.获取网络到内存的一个输入流
            input = socket.getInputStream();//客户端说了什么
            // 4.读取数据,这个数据是Client发过来的
            byte[] arr = new byte[1024];
            int len = input.read(arr);
            Request request = (Request) SerializeUtil.unserialize(arr);
            String serviceName = request.getServiceName();
            //Object target = spring.get(serviceName);
            // Class clazz = target.getClass();
            Class clazz=Class.forName(serviceName);
            Object target = spring.getBean(clazz);

            Method method = clazz.getMethod(request.getMethodName(), request.getParamTypes());
            Object result = method.invoke(target, request.getArgs());

            // 6.服务端给客户端回复消息
            output = socket.getOutputStream();//对客户端说的话
            output.write(SerializeUtil.serialize(result));
            output.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                output.close();
                input.close();
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
